﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Text;

namespace lib.Twitter
{
    public class TwitterLinq
    {
        //Get a datacontext connected to local db 
        private static TwitterDataContext dataContext
        {
            get
            {
                //Create datacontext test it and return it
                TwitterDataContext dc = new TwitterDataContext(DataAccessLayer.DAL.connectionString);
                if (!dc.DatabaseExists())
                {
                    Debug.WriteLine("COULD NOT OPEN DATABASE PLZ COPY DB.SDF TO BIN DIRECTORY");
                    throw new lib.CustomExceptions.DataContextDBDoesNotExist("Could not open DB.");
                }
                return dc;
            }
        }

        //Get All Users as list
        public static List<User> getTwitterUsers()
        {
            IQueryable<User> result;
            using (TwitterDataContext conn = dataContext)
            {
                result = from u in conn.Users
                         select u;
                return result.ToList<User>();
            }
        }

        //Get one user by Status
        public static User getTwitterUserByStatus(Status s)
        {
            IQueryable<User> result;
            using (TwitterDataContext conn = dataContext)
            {
                result = from u in conn.Users
                         where u.id == s.user_id
                         select u;
                return result.ToList<User>()[0];
            }
        }


        //Get one user by name
        public static User getTwitterUserByName(String s)
        {
            IQueryable<User> result;
            using (TwitterDataContext conn = dataContext)
            {
                result = from u in conn.Users
                         where u.screen_name == s
                         select u;
                if (result.Count() > 0)
                    return result.ToList<User>()[0];
                else
                    return null;
            }
        }


        //Get all statuses as list
        public static List<Status> getTwitterStatuses()
        {
            IQueryable<Status> result;
            using (TwitterDataContext conn = dataContext)
            {
                result = from s in conn.Statuses
                         select s;
                return result.ToList<Status>();
            }
        }


        //Get ordered Statuses only first 10
        public static List<Status> getOrderedStatuses()
        {
            IQueryable<Status> result;
            using (TwitterDataContext conn = dataContext)
            {
                result = (from s in conn.Statuses
                          orderby s.created_at descending
                          select s).Take(20);
                return result.ToList<Status>();
            }
        }


        //Get username form id
        public static string getUserNameById(int user_id)
        {
            using (TwitterDataContext conn = dataContext)
            {
                var res = (from u in conn.Users
                           where u.id == user_id
                           select u);
                return res.ToList<User>()[0].name;
            }
        }


        // insert status and users object into DB
        // return true if there is a new status
        public static bool insertTwitter(List<Object> olist,User myUser)
        {
            List<User> addedUsers = new List<User>();
            List<Status> addedStatuses = new List<Status>();
            bool newStatus = false;

            
            using (TwitterDataContext conn = dataContext)
            {

                //insert object!
                try
                {

                    foreach (Object o in olist)
                    {
                        if (o is User)
                        {
                            User twUser = (User)o;
                            int iu = (from u in conn.Users
                                      where u.id == twUser.id
                                      select u).Count();

                            bool addUser = (iu == 0);
                            if (addUser)
                            {
                                addedUsers.Add(twUser);
                                conn.Users.InsertOnSubmit(twUser);
                                conn.SubmitChanges();
                            }
                        }
                        else if (o is Status)
                        {
                            Status twStatus = (Status)o;

                            int ist = (from s in conn.Statuses
                                       where s.id == twStatus.id
                                       select s).Count();
                            bool addStatus = (ist == 0);
                            if (addStatus)
                            {
                                addedStatuses.Add(twStatus);
                                conn.Statuses.InsertOnSubmit(twStatus);
                                conn.SubmitChanges();
                            }
                        }
                    }


                }
                catch (Exception ex){
                    Debug.WriteLine(ex.Message);
                    throw ex;
                }
                
                //Only statuses not from me
                if (myUser != null)
                {
                    newStatus = (from s in addedStatuses
                                 where s.user_id != myUser.id
                                 select s).Count() > 0;
                }
                else
                {
                    if (addedStatuses.Count() > 0)
                    {
                        newStatus = true;
                    }
                }
                #region deleteRemoved
                /*   Needs to be refactored             
                //Delete statuses not appearing in feed anymore
                if (Settings.deleteRemovedStatus)
                {
                    //All statuses from current request and cast to Status
                    var online_statuses = from s in olist
                                          where (s is Status)
                                          select s;
                    var os = online_statuses.Cast<Status>().ToList<Status>();

                    //get the lowest id form Online statuses
                    long lowest_id = os.Max(s => s.id);

                    //Get all statuses equal or higher to lowest id
                    var db_statuses = from s in conn.Statuses
                                      where s.id >= lowest_id
                                      select s;
                    var ds = db_statuses.ToList<Status>();

                    var to_delete = ds.Except(os);
                    //delete the statuses
                    foreach (Status sta in to_delete)
                    {
                        conn.Statuses.DeleteOnSubmit(sta);
                    }


                    conn.SubmitChanges();
                }
                */
                #endregion deleteRemoved

            }

            return newStatus;
        }

        

        //reset db
        public static void ResetDB()
        {
            using (TwitterDataContext conn = dataContext)
            {
                var us = from s in conn.Users
                         select s;
                if (us.Count() > 0)
                {
                    conn.Users.DeleteAllOnSubmit(us);
                }
                var st = from s in conn.Statuses
                         select s;
                if (st.Count() > 0)
                {
                    conn.Statuses.DeleteAllOnSubmit(st);
                }
                conn.SubmitChanges();
            }

        }


        //Set read status
        public static void SetStatusToRead(Status s_in)
        {
            IQueryable<Status> result;
            using (TwitterDataContext conn = dataContext)
            {
                result = from s in conn.Statuses
                         where s.id == s_in.id
                         select s;
                try
                {
                    result.ToList<Status>()[0].read = 1;
                    conn.SubmitChanges();
                }
                catch { }
            }

        }

        //Set unread status
        public static void SetStatusToUnread(Status s_in)
        {
            IQueryable<Status> result;
            using (TwitterDataContext conn = dataContext)
            {
                result = from s in conn.Statuses
                         where s.id == s_in.id
                         select s;
                result.ToList<Status>()[0].read = 0;
                conn.SubmitChanges();
            }
        }


    }
}
